<template>
  <div class="chat-app">
    <div class="chat-header">
      <h1>AI编程小助手</h1>
      <div class="room-info">
        聊天室ID: {{ roomId }}
      </div>
    </div>
    
    <div id="chat-container" class="chat-container">
      <div v-for="message in messages" :key="message.id" :class="['message', message.type]">
        <div class="message-content" v-html="message.type === 'ai' ? renderMarkdown(message.content) : message.content">
        </div>
        <div class="message-avatar">
          {{ message.type === 'user' ? '👤' : '🤖' }}
        </div>
      </div>
      
      <div v-if="isLoading" class="loading-indicator">
        <span class="loading-dots">AI正在输入...</span>
      </div>
    </div>
    
    <div class="chat-input-area">
      <input 
        v-model="inputMessage" 
        type="text" 
        placeholder="请输入您的问题..."
        @keyup.enter="sendMessage"
        :disabled="isLoading"
        class="message-input"
      />
      <button 
        @click="sendMessage"
        :disabled="isLoading || !inputMessage.trim()"
        class="send-button"
      >
        发送
      </button>
    </div>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      roomId: '',
      messages: [],
      inputMessage: '',
      isLoading: false,
      eventSource: null
    }
  },
  mounted() {
    // 生成随机的聊天室ID
    this.roomId = this.generateRoomId();
    
    // 添加欢迎消息
    this.messages.push({
      id: Date.now(),
      type: 'ai',
      content: '欢迎使用瑞奇AI编程小助手！请输入您的问题，我会为您解答。'
    });
  },
  beforeUnmount() {
    // 当组件卸载时关闭SSE连接
    if (this.eventSource) {
      this.eventSource.close();
    }
  },
  methods: {
    // 简单的Markdown渲染函数
    renderMarkdown(text) {
      if (!text) return '';
      
      // 创建临时变量存储代码块，以避免在其他转换中被处理
      const codeBlocks = [];
      let html = text
        // 首先保存所有代码块，避免在后续转换中被修改
        .replace(/```(\w*\s*)([\s\S]*?)```/g, (match, language, code) => {
          const id = `code-block-${codeBlocks.length}`;
          codeBlocks.push({ id, language, code });
          return `{{${id}}}`;
        })
        // 保存行内代码
        .replace(/`(.*?)`/g, (match, code) => {
          const id = `inline-code-${codeBlocks.length}`;
          codeBlocks.push({ id, type: 'inline', code });
          return `{{${id}}}`;
        });
      
      // 现在处理其他Markdown元素
      html = html
        // 标题 - 添加h4-h6支持
        .replace(/^# (.*$)/gm, '<h1>$1</h1>')
        .replace(/^## (.*$)/gm, '<h2>$1</h2>')
        .replace(/^### (.*$)/gm, '<h3>$1</h3>')
        .replace(/^#### (.*$)/gm, '<h4>$1</h4>')
        .replace(/^##### (.*$)/gm, '<h5>$1</h5>')
        .replace(/^###### (.*$)/gm, '<h6>$1</h6>')
        // 链接
        .replace(/\[(.*?)\]\((.*?)\)/g, '<a href="$2" target="_blank" class="markdown-link">$1</a>')
        // 列表
        .replace(/^- (.*$)/gm, '<ul><li>$1</li></ul>')
        .replace(/^\d+\. (.*$)/gm, '<ol><li>$1</li></ol>')
        // 粗体
        .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
        // 斜体
        .replace(/\*(.*?)\*/g, '<em>$1</em>')
        // 段落 - 排除已经是代码块的行
        .replace(/^(?!<h|<ul|<ol|<pre|<code|<a).*$/gm, '<p>$&</p>');
      
      // 处理连续的列表项
      html = html.replace(/<\/ul>\s*<ul>/g, '')
                .replace(/<\/ol>\s*<ol>/g, '')
                .replace(/<\/li>\s*<li>/g, '</li><li>');
      
      // 最后将保存的代码块替换回去，确保HTML特殊字符被正确转义
      codeBlocks.forEach(block => {
        if (block.type === 'inline') {
          const escapedCode = block.code.replace(/&/g, '&amp;')
                                      .replace(/</g, '&lt;')
                                      .replace(/>/g, '&gt;')
                                      .replace(/"/g, '&quot;')
                                      .replace(/'/g, '&#039;');
          html = html.replace(`{{${block.id}}}`, `<code>${escapedCode}</code>`);
        } else {
          // 清理代码块内容，确保HTML特殊字符被转义
          const escapedCode = block.code.replace(/&/g, '&amp;')
                                      .replace(/</g, '&lt;')
                                      .replace(/>/g, '&gt;')
                                      .replace(/"/g, '&quot;')
                                      .replace(/'/g, '&#039;');
          // 去除语言标记中的空白字符
          const lang = block.language.trim();
          // 如果有语言标记，添加到class中
          const codeClass = lang ? ` language-${lang}` : '';
          html = html.replace(`{{${block.id}}}`, `<pre class="code-block"><code class="${codeClass}">${escapedCode}</code></pre>`);
        }
      });
      
      return html;
    },
    // 生成随机聊天室ID
    generateRoomId() {
      // 生成5位以内的数字ID，确保在JavaScript的安全整数范围内
      // 并且确保是纯数字类型
      return Math.floor(Math.random() * 99999) + 1;
    },
    
    // 发送消息
    async sendMessage() {
      if (!this.inputMessage.trim() || this.isLoading) return;
      
      // 添加用户消息到聊天记录
      const userMessage = {
        id: Date.now(),
        type: 'user',
        content: this.inputMessage.trim()
      };
      this.messages.push(userMessage);
      
      // 清空输入框
      this.inputMessage = '';
      
      // 滚动到底部
      await this.$nextTick();
      this.scrollToBottom();
      
      // 开始加载状态
      this.isLoading = true;
      
      try {
        // 确保关闭任何现有的SSE连接
        if (this.eventSource) {
          this.eventSource.close();
          this.eventSource = null;
        }
        
        // 使用SSE调用chat接口，roomId已经是数字类型
        const url = `http://localhost:8081/api/ai/chat?memoryId=${this.roomId}&message=${encodeURIComponent(userMessage.content)}`;
        this.eventSource = new EventSource(url);
        
        // 创建AI回复消息
        const aiMessage = {
          id: Date.now() + 1,
          type: 'ai',
          content: ''
        };
        this.messages.push(aiMessage);
        
        // 监听SSE事件
        this.eventSource.onmessage = (event) => {
          if (event.data) {
            // 检查是否收到结束标记
            if (event.data === '[DONE]') {
              // 响应已完成，关闭连接
              if (this.eventSource) {
                this.eventSource.close();
                this.eventSource = null;
              }
              this.isLoading = false;
              return;
            }
            
            aiMessage.content += event.data;
            // 强制Vue更新DOM，实现实时流式显示效果
            this.$forceUpdate();
            this.$nextTick(() => this.scrollToBottom());
          }
        };
        
        this.eventSource.onopen = () => {
          console.log('SSE连接已打开');
        };
        
        this.eventSource.onerror = (error) => {
          console.error('SSE连接错误:', error);
          this.isLoading = false;
          if (this.eventSource) {
            this.eventSource.close();
            this.eventSource = null;
          }
        };
        
        this.eventSource.onclose = () => {
          console.log('SSE连接已关闭');
          this.isLoading = false;
          this.eventSource = null;
        };
        
      } catch (error) {
        console.error('发送消息失败:', error);
        this.isLoading = false;
        if (this.eventSource) {
          this.eventSource.close();
          this.eventSource = null;
        }
        // 添加错误消息
        this.messages.push({
          id: Date.now() + 2,
          type: 'error',
          content: '抱歉，无法连接到服务器，请稍后再试。'
        });
        await this.$nextTick();
        this.scrollToBottom();
      }
    },
    
    // 滚动到底部
    scrollToBottom() {
      const chatContainer = document.getElementById('chat-container');
      if (chatContainer) {
        chatContainer.scrollTop = chatContainer.scrollHeight;
      }
    }
  }
}
</script>

<style scoped>
.chat-app {
  display: flex;
  flex-direction: column;
  height: 100vh;
  max-width: 1200px;
  margin: 0 auto;
  background-color: #f5f5f5;
}

.chat-header {
  background-color: #4a6fa5;
  color: white;
  padding: 1rem 2rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.chat-header h1 {
  margin: 0;
  font-size: 1.5rem;
}

.room-info {
  font-size: 0.9rem;
  opacity: 0.9;
}

.chat-container {
  flex: 1;
  overflow-y: auto;
  padding: 1rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.message {
  display: flex;
  max-width: 70%;
  word-wrap: break-word;
}

.message.user {
  align-self: flex-end;
  flex-direction: row-reverse;
}

.message.ai {
  align-self: flex-start;
}

.message-content {
  padding: 0.75rem 1rem;
  border-radius: 18px;
  line-height: 1.4;
}

/* Markdown样式支持 */
.message-content h1, .message-content h2, .message-content h3, .message-content h4, .message-content h5, .message-content h6 {
  margin: 1rem 0 0.5rem 0;
  line-height: 1.2;
  font-weight: 600;
}

/* Markdown链接样式 */
.message-content .markdown-link {
  color: #4a6fa5;
  text-decoration: none;
  border-bottom: 1px solid #4a6fa5;
  transition: all 0.2s ease;
}

.message-content .markdown-link:hover {
  color: #3a5a8a;
  border-bottom-color: #3a5a8a;
  text-decoration: underline;
}

/* 用户消息中的链接样式 */
.message.user .message-content .markdown-link {
  color: #a5c8ff;
  border-bottom-color: #a5c8ff;
}

.message.user .message-content .markdown-link:hover {
  color: #8ab8ff;
  border-bottom-color: #8ab8ff;
}

.message-content h1 {
  font-size: 1.5rem;
  color: #2d3748;
}

.message-content h2 {
  font-size: 1.3rem;
  color: #4a5568;
}

.message-content h3 {
  font-size: 1.1rem;
  color: #718096;
}

.message-content h4 {
  font-size: 1rem;
  color: #718096;
}

.message-content h5 {
  font-size: 0.9rem;
  color: #a0aec0;
}

.message-content h6 {
  font-size: 0.8rem;
  color: #a0aec0;
}

.message-content ul, .message-content ol {
  margin: 0.5rem 0;
  padding-left: 1.5rem;
}

.message-content p {
  margin: 0.75rem 0;
  line-height: 1.6;
}

/* 优化列表样式 */
.message-content ul, .message-content ol {
  margin: 0.75rem 0;
  padding-left: 1.5rem;
}

.message-content li {
  margin-bottom: 0.5rem;
  line-height: 1.6;
}

.message-content pre {
  background-color: #f5f5f5;
  padding: 0.75rem;
  border-radius: 8px;
  overflow-x: auto;
  margin: 0.75rem 0;
}

/* 改进的代码块样式 */
.message-content .code-block {
  background-color: #2d3748;
  color: #e2e8f0;
  padding: 1rem;
  border-radius: 8px;
  overflow-x: auto;
  margin: 1rem 0;
  border-left: 4px solid #4a6fa5;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.message-content .code-block code {
  background-color: transparent;
  color: #e2e8f0;
  font-family: 'Fira Code', 'Courier New', Courier, monospace;
  font-size: 0.9rem;
  line-height: 1.5;
}

.message-content code {
  background-color: #f5f5f5;
  padding: 0.2rem 0.4rem;
  border-radius: 4px;
  font-family: 'Courier New', Courier, monospace;
  font-size: 0.9rem;
}

.message-content pre code {
  background-color: transparent;
  padding: 0;
}

.message.user .message-content {
  background-color: #4a6fa5;
  color: white;
  border-bottom-right-radius: 6px;
}

.message.ai .message-content {
  background-color: #f8f9fa;
  color: #2d3748;
  border-bottom-left-radius: 6px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
  font-size: 1rem;
  line-height: 1.6;
}

.message-avatar {
  display: flex;
  align-items: flex-end;
  margin: 0 0.5rem;
  font-size: 1.5rem;
}

.loading-indicator {
  align-self: flex-start;
  padding: 0.5rem 1rem;
  color: #666;
  font-size: 0.9rem;
}

.loading-dots::after {
  content: '';
  animation: dots 1.5s infinite;
}

@keyframes dots {
  0%, 20% { content: '.'; }
  40% { content: '..'; }
  60% { content: '...'; }
  80%, 100% { content: ''; }
}

.chat-input-area {
  display: flex;
  padding: 1rem;
  background-color: white;
  border-top: 1px solid #ddd;
  gap: 0.5rem;
}

.message-input {
  flex: 1;
  padding: 0.75rem 1rem;
  border: 1px solid #ddd;
  border-radius: 20px;
  font-size: 1rem;
  outline: none;
  transition: border-color 0.2s;
}

.message-input:focus {
  border-color: #4a6fa5;
}

.message-input:disabled {
  background-color: #f5f5f5;
  cursor: not-allowed;
}

.send-button {
  padding: 0.75rem 1.5rem;
  background-color: #4a6fa5;
  color: white;
  border: none;
  border-radius: 20px;
  font-size: 1rem;
  cursor: pointer;
  transition: background-color 0.2s;
}

.send-button:hover:not(:disabled) {
  background-color: #3a5a8a;
}

.send-button:disabled {
  background-color: #ccc;
  cursor: not-allowed;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .chat-app {
    height: 100vh;
    max-width: none;
  }
  
  .message {
    max-width: 85%;
  }
}
</style>
